use thiserror::Error;
use super::api;
use super::capability::ThreadSafeCapability;

// 定义IO错误类型
#[derive(Error, Debug)]
pub enum IoError {
    #[error("IO operation failed")]
    OperationFailed,
    
    #[error("Invalid IO capability")]
    InvalidCapability,
    
    #[error("Invalid port address")]
    InvalidPort,
}

// 定义IO结果类型
pub type IoResult<T> = Result<T, IoError>;

// IO端口管理器
pub struct IoPortManager {
    capability: ThreadSafeCapability,
}

impl IoPortManager {
    // 创建新的IO端口管理器
    pub fn new(capability: ThreadSafeCapability) -> IoResult<Self> {
        // 验证能力是否为IO类型
        if let Ok(cap) = capability.lock() {
            if cap.resource_type() != super::super::core::types::ResourceType::Io {
                return Err(IoError::InvalidCapability);
            }
        } else {
            return Err(IoError::InvalidCapability);
        }
        
        Ok(IoPortManager {
            capability,
        })
    }
    
    // 从IO端口读取字节
    #[allow(unused_comparisons)]
    pub fn inb(&self, port: u16) -> IoResult<u8> {
        // 验证端口地址是否有效（这里简单验证）
        if port > 0xFFFF {
            return Err(IoError::InvalidPort);
        }
        
        // 获取能力ID
        let cap_id = if let Ok(cap) = self.capability.lock() {
            cap.id()
        } else {
            return Err(IoError::OperationFailed);
        };
        
        // 调用FFI从IO端口读取
        let value = unsafe {
            api::exokernel_inb(cap_id, port)
        };
        
        Ok(value)
    }
    
    // 向IO端口写入字节
    #[allow(unused_comparisons)]
    pub fn outb(&self, port: u16, value: u8) -> IoResult<()> {
        // 验证端口地址是否有效（这里简单验证）
        if port > 0xFFFF {
            return Err(IoError::InvalidPort);
        }
        
        // 获取能力ID
        let cap_id = if let Ok(cap) = self.capability.lock() {
            cap.id()
        } else {
            return Err(IoError::OperationFailed);
        };
        
        // 调用FFI向IO端口写入
        unsafe {
            api::exokernel_outb(cap_id, port, value);
        }
        
        Ok(())
    }
}